<?php
/*
Auth:Sang
Desc:应用服务器类
Date:2014-11-01
*/
namespace Lib;

class AppServer extends HttpServer{
    public $worker;
    private $auto_load = array('cache','session','db','storage');
    public function __construct($config){
        parent::__construct($config);
        Loader::setRootNS('App',DOCUMENT_ROOT);
        Loader::setRootNS('Act',APP_PATH.'Act/');
        Loader::setRootNS('Widget',WIDGET_PATH);
        Loader::setRootNS('Task',DOCUMENT_ROOT.'/Task/');
        $_SERVER['DOCUMENT_ROOT'] = DOCUMENT_ROOT;
        if(!empty($this->c('app.charset'))){
            $this->charset = $this->c('app.charset');
        }
        \Lib\Error::$echo_html = true;
        set_error_handler(array($this,'errorHandler'));
    }

    public function __get($name){
        if(empty($this->$name) && in_array($name,$this->auto_load)){
            $class = '\\Lib\\'.ucwords($name);
            $this->$name = new $class(isset($this->config[$name]) ? $this->config[$name] : array());
        }
        return $this->$name;
    }

    public function __set($name,$val){
        $this->$name = $val;
    }
    public function __isset($name){
        return isset($this->$name);
    }

	public function start($serv){
        $this->worker = $serv;
        $path_info = trim($_SERVER['PATH_INFO'],'/');
        $request_methods = array('get'=>'doGet','post'=>'doPost','add'=>'doAdd','update'=>'doUpdate','delete'=>'doDelete','ajax'=>'doAjax');
        $act = 'index';
        $method = $request = 'get';
        empty($path_info) && $path_info = $act;
        
        $reqs = explode('/',$path_info);
        if(!empty($path_info) && count($reqs)==1){
            $act = $reqs[0];
            if(is_post()){
                $method = 'post';
            }
        }elseif(count($reqs)>1){
            $m = array_pop($reqs);
            if(in_array($m,array_keys($request_methods))){
                $request = $method = $m;
            }else{
                $reqs[] = $m;
                if(is_post()){
                    $method = 'post';
                }
            }
            array_walk($reqs,function(&$v,$k){$v = ucwords($v);});
            $act = join('\\',$reqs);
        }

        $act = ucwords($act);
        $act_class = '\\Act\\'.$act;
        $act_file = APP_PATH.'Act/'.str_replace('\\','/',$act).'.php';
        if(!in_array($method,array_keys($request_methods)) || !is_file($act_file) || !class_exists($act_class)){
        	return $this->http404();
        }
        try{
            apply_action('app_start',$act_file);
            $this->session->start();
            ob_start();
            $act_obj = new $act_class($this,$request);
            $data = $act_obj->$request_methods[$method]();
            apply_action('on_response',$data);
            $data .= ob_get_contents();
            !is_ajax() && $data .= '<!--pageId:'.$act_obj->page_id.'-->';
            ob_end_clean();
            $this->response($data);
        }catch(\Exception $e){
            if(!$e->getMessage()){
                $this->response('');
            }else{
                if(defined('DEBUG')){
                    $info = 'Code:'.$e->getCode().' '.$e->getMessage();
                    if($e->getCode()>1){
                        $file = explode('.',$e->getFile())[0];
                        $info .= '<br>in '.str_replace([SHM_PATH,APP_PATH,FRAME_ROOT],'',$file).' : '.$e->getLine();
                    }

                    $error = \Lib\Error::info('Runtime error:',$info,$e->getCode()>1?1:0);
                }else{
                    $error = \Lib\Error::info('','页面发生错误<hr>请联系：190276134@qq.com',0);
                }
                $this->response($error);
            }
        }finally{
            //自动保存session
            $this->session->save();
            //当内存占用率过大时，自动退出重启
            $memory_used = memory_get_peak_usage(true);
            if($memory_used/1024/1024 > 100){
                exit;
            }
        }
	}

    public function errorHandler($errno, $errstr, $errfile, $errline){
        $errfile = explode('.',$errfile)[0];
        $errorMsg = "{$errstr} (".str_replace(array(SHM_PATH.'tpls/',SHM_PATH.'widget/tpl/',APP_PATH,FRAME_ROOT),array('tpl:','widget_tpl:','app:','root:'),$errfile).":{$errline})";
        $this->response(\Lib\Error::info("Runtime Error", $errorMsg));
    }
}